package com.einmeer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.einmeer.entity.SysFile;
import com.einmeer.mapper.SysFileMapper;
import com.einmeer.service.SysFileService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.compress.utils.FileNameUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * <p>
 * 系统文件表 服务实现类
 * </p>
 *
 * @author einmeer
 * @since 2024-03-18
 */
@Service
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements SysFileService {
    @Value("${minio.url}")
    String url;
    @Value("${minio.username}")
    String username;
    @Value("${minio.password}")
    String password;

    @Override
    public String upload(MultipartFile file, String bucket) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 获取md5大小类型
        String md5 = DigestUtils.md5Hex(file.getInputStream());
        long size = file.getSize();
        String contentType = file.getContentType();
        // 通过md5 大小类型到数据库查询
        SysFile sysFile = get(md5, size, contentType);
        if (null != sysFile){
            // 如果不是空数据库中有，直接返回上次路径
            return sysFile.getPath();
        }
        // 如果没有传过，上传，长传前重命名
        StringBuilder name = new StringBuilder();
        name.append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")))
                .append(RandomStringUtils.random(6,false,true))
                .append(".")
                .append(FileNameUtils.getExtension(file.getOriginalFilename()));
        // 创建Minio客户端
        MinioClient client = MinioClient.builder()
                .endpoint(url)
                .credentials(username,password)
                .build();
        // 定义上传参数
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(bucket)
                .stream(file.getInputStream(),size,0)
                .contentType(contentType)
                .object(name.toString())
                .build();
        // 上传
        client.putObject(args);
        // 上传后保存到数据库，下次再传就能识别出上传过的文件
        StringBuilder path = new StringBuilder();
        path.append(url)
                .append("/").append(bucket)
                .append("/").append(name.toString());
        sysFile = new SysFile(md5,size,contentType,path.toString(),bucket);
        this.save(sysFile);
        return path.toString();
    }

    private SysFile get(String md5, long size, String contentType) {
        QueryWrapper<SysFile> wrapper = new QueryWrapper<>();
        wrapper.eq("md5", md5)
                .eq("size", size)
                .eq("content_type", contentType);
        return this.getOne(wrapper);
    }
}
